commonlibsse_ng\re\u/
UI.rs1use core::ffi::{CStr, c_void};
2
3use crate::re::BSAtomic::BSSpinLock;
4use crate::re::BSFixedString::BSFixedString;
5use crate::re::BSTArray::BSTArray;
6use crate::re::BSTEvent::{BSTEventSink, BSTEventSource};
7use crate::re::BSTHashMap::BSTHashMap;
8use crate::re::BSTimer::BSTimer;
9use crate::re::GFxMovieView;
10use crate::re::GPtr::GPtr;
11use crate::re::IMenu::IMenu;
12use crate::re::MenuModeChangeEvent::MenuModeChangeEvent;
13use crate::re::MenuOpenCloseEvent::MenuOpenCloseEvent;
14
15#[rustfmt::skip]
16#[repr(C)]
17#[derive(Debug)]
18pub struct UI {
19 pub __base : [u8; 8], pub __base1: BSTEventSource<MenuOpenCloseEvent>, pub __base2: BSTEventSource<MenuModeChangeEvent>, pub __base3: BSTEventSource<*mut c_void>, pub menuStack: BSTArray<GPtr<IMenu>>, pub menuMap: BSTHashMap<BSFixedString, UIMenuEntry>, pub processMessagesLock: BSSpinLock, pub numPausesGame: u32, pub numItemMenus: u32, pub numDisablePauseMenu: u32, pub numAllowSaving: u32, pub numDontHideCursorWhenTopmost: u32, pub numCustomRendering: u32, pub numApplicationMenus: u32, pub modal: bool, pub pad17D: u8, pub pad17E: u16, pub uiTimer: BSTimer, pub menuSystemVisible: bool, pub closingAllMenus: bool, pub pad1C2: u16, pub pad1C4: u32, pub unk1C8: u32, pub unk1CA: u32, }
44const _: () = assert!(core::mem::size_of::<UI>() == 0x1D0);
45
46pub trait HasMenuName {
47 const MENU_NAME: &'static CStr;
48}
49
50impl UI {
51 #[commonlibsse_ng_derive_internal::relocate(
53 cast_as = "*mut *mut UI",
54 default = "None",
55 deref_once,
56 id(se = 514178, ae = 400327)
57 )]
58 #[inline]
59 pub fn get_singleton() -> Option<&'static UI> {
60 |deref_type: DerefType| unsafe { deref_type.as_ref() }
61 }
62
63 #[commonlibsse_ng_derive_internal::relocate(
65 cast_as = "*mut *mut UI",
66 default = "None",
67 deref_once,
68 id(se = 514178, ae = 400327)
69 )]
70 #[inline]
71 pub fn get_singleton_mut() -> Option<&'static mut UI> {
72 |deref_type: DerefType| unsafe { deref_type.as_mut() }
73 }
74
75 #[inline]
77 pub const fn game_is_paused(&self) -> bool {
78 self.numPausesGame > 0
79 }
80
81 #[inline]
83 pub fn get_menu(&self, menu_name: &CStr) -> Option<GPtr<IMenu>> {
84 self.menuMap
85 .get(&BSFixedString::new(menu_name))
86 .map(|menu_entry| GPtr::clone(&menu_entry.menu))
87 }
88
89 #[inline]
91 pub fn get_movie_view(&self, menu_name: &CStr) -> Option<GPtr<GFxMovieView>> {
92 self.get_menu(menu_name).map(|menu_ptr| GPtr::clone(&menu_ptr.uiMovie))
93 }
94
95 #[inline]
97 pub const fn is_cursor_hidden_when_topmost(&self) -> bool {
98 self.numDontHideCursorWhenTopmost == 0
99 }
100
101 #[inline]
103 pub const fn is_item_menu_open(&self) -> bool {
104 self.numItemMenus > 0
105 }
106
107 #[inline]
109 pub fn is_menu_open(&self, menu_name: &CStr) -> bool {
110 self.get_menu(menu_name).is_some_and(|menu_ptr| menu_ptr.on_stack())
111 }
112
113 #[inline]
115 pub const fn is_modal_menu_open(&self) -> bool {
116 self.modal
117 }
118
119 #[inline]
121 pub const fn is_pause_menu_disabled(&self) -> bool {
122 self.numDisablePauseMenu > 0
123 }
124
125 #[inline]
127 pub const fn is_saving_allowed(&self) -> bool {
128 self.numAllowSaving > 0
129 }
130
131 #[inline]
133 pub const fn is_showing_menus(&self) -> bool {
134 self.menuSystemVisible
135 }
136
137 #[inline]
139 pub const fn is_using_custom_rendering(&self) -> bool {
140 self.numCustomRendering > 0
141 }
142
143 #[inline]
145 pub fn register(&mut self, menu_name: &CStr, creator: fn() -> *mut IMenu) {
146 self.menuMap.insert(BSFixedString::new(menu_name), UIMenuEntry::new(GPtr::null(), creator));
147 }
148
149 #[inline]
151 pub const fn show_menus(&mut self, show: bool) {
152 self.menuSystemVisible = show;
153 }
154
155 #[inline]
156 pub fn get_menu_by_name<T>(&self, name: &CStr) -> Option<GPtr<T>>
157 where
158 T: crate::re::GPtr::RefCounted,
159 {
160 self.get_menu(name).map(|menu_ptr| menu_ptr.cast::<T>())
161 }
162
163 #[inline]
164 pub fn get_menu_as<T>(&self) -> Option<GPtr<T>>
165 where
166 T: HasMenuName + crate::re::GPtr::RefCounted,
167 {
168 self.get_menu_by_name::<T>(T::MENU_NAME)
169 }
170}
171
172macro_rules! impl_ui_event_sink {
173 (
174 $(
175 ($add_fn:ident, $remove_fn:ident, $field:ident, $event_ty:ty)
176 ),*
177 $(,)?
178 ) => {
179 impl UI {
180 $(
181 pub fn $add_fn(&mut self, sink: *mut BSTEventSink<$event_ty>) {
182 self.$field.add_event_sink(sink);
183 }
184
185 pub fn $remove_fn(&mut self, sink: *mut BSTEventSink<$event_ty>) {
186 self.$field.remove_event_sink(sink);
187 }
188 )*
189 }
190 };
191}
192impl_ui_event_sink! {
193 (add_menu_open_close_sink, remove_menu_open_close_sink, __base1, MenuOpenCloseEvent),
194 (add_menu_mode_change_sink, remove_menu_mode_change_sink, __base2, MenuModeChangeEvent),
195 (add_void_sink, remove_void_sink, __base3, *mut c_void),
196}
197
198#[repr(C)]
199#[derive(Debug)]
200pub struct UIMenuEntry {
201 pub menu: GPtr<IMenu>, pub menuCreator: fn() -> *mut IMenu, }
204const _: () = assert!(core::mem::size_of::<UIMenuEntry>() == 0x10);
205
206impl UIMenuEntry {
207 #[inline]
208 pub const fn new(menu: GPtr<IMenu>, menu_creator: fn() -> *mut IMenu) -> Self {
209 Self { menu, menuCreator: menu_creator }
210 }
211}